/*
番号：H3cIOT-001
                                       FBI Warning
Federal law provides severe civil and criminal penalties for the unauthorized reproduction,
distribution,or exhibition of copyrighted motion pictures(Title 17, United States Code, Sections 501 and 508).
The federal bureau of Investigation investigate allegations of criminal copyright infringement.
(Title 17, United States Code, Section 506)
版权所有 2003-2018 新华三技术有限公司.保留一切权利.
 */
package com.example.demo.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.annotation.Verify;
import com.example.demo.utils.H3cIotExceptionUtil;
import com.example.demo.utils.VerifyUtil;
import com.h3c.iotframework.annotation.VerifyInteger;
import com.h3c.iotframework.annotation.VerifyList;
import com.h3c.iotframework.annotation.VerifyString;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;


/**
 * @author xieluoyin
 */
@Aspect
@Component
@Slf4j
public class VerifyAdvice {
    @Pointcut("execution(public * com.example.demo.service..*(..))")
    public void verify() {

    }

    @Before(value = "verify()")
    public void before(JoinPoint joinPoint) {

        long startTime = System.currentTimeMillis();

        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Annotation[][] parameterAnnotationSS = method.getParameterAnnotations();

        for (Annotation[] parameterAnnotations : parameterAnnotationSS) {
            for (Annotation parameterAnnotation : parameterAnnotations) {
                if (parameterAnnotation.annotationType().equals(Verify.class)) {
                    Object[] args = joinPoint.getArgs();
                    for (Object arg : args) {
                        String text = JSONObject.toJSONString(arg);
                        JSONObject jsonObject = JSONObject.parseObject(
                                text);
                        Field[] fields = arg.getClass().getDeclaredFields();
                        for (Field field : fields) {
                            Annotation[] declaredAnnotations = field.getDeclaredAnnotations();
                            String fieldName = field.getName();
                            for (Annotation declaredAnnotation : declaredAnnotations) {
                                if (declaredAnnotation.annotationType().equals(VerifyString.class)) {
                                    String sValue = jsonObject.getString(fieldName);
                                    VerifyString verifyString = (VerifyString) declaredAnnotation;
                                    verifyString(field,fieldName, sValue, verifyString);
                                }
                                if (declaredAnnotation.annotationType().equals(VerifyInteger.class)) {
                                    Integer iValue = jsonObject.getInteger(fieldName);
                                    VerifyInteger verifyInteger = (VerifyInteger) declaredAnnotation;
                                    verifyInteger(field,fieldName, iValue, verifyInteger);
                                }
                                if (declaredAnnotation.annotationType().equals(VerifyList.class)) {
                                    Collection cValue = jsonObject.getJSONArray(fieldName);
                                    VerifyList verifyCollection = (VerifyList) declaredAnnotation;
                                    verifyCollection(field,fieldName, cValue,verifyCollection);
                                }


                            }
                        }
                    }
                    log.info("参数验证通过花费{}秒{}",
                            (System.currentTimeMillis() - startTime) / 1000.0, args);
                }
            }
        }

    }

    private void verifyCollection(Field field, String fieldName, Collection cValue, VerifyList verifyCollection) {

        if (!field.getType().equals(ArrayList.class)){
            H3cIotExceptionUtil.errorInAnnotationConfiguration(fieldName);
        }
        //验证canEmpty
        if (!verifyCollection.canEmpty()) {
            VerifyUtil.verifyCollectionEmpty(fieldName, cValue, verifyCollection.message());
        }

        //验证maxLength
        if (verifyCollection.maxLength() > 0) {
            VerifyUtil.verifyCollectionEmpty(fieldName, cValue, verifyCollection.message());
            VerifyUtil.verifyMax(fieldName, cValue.size(), verifyCollection.message(),
                    verifyCollection.minLength(), verifyCollection.maxLength());
        }
        //验证minLength
        if (verifyCollection.minLength() > 0) {
            VerifyUtil.verifyCollectionEmpty(fieldName, cValue, verifyCollection.message());
            VerifyUtil.verifyMin(fieldName, cValue.size(), verifyCollection.message(),
                    verifyCollection.minLength(), verifyCollection.maxLength());
        }
    }

    private void verifyInteger(Field field,String fieldName, Integer iValue, VerifyInteger verifyInteger) {
        if (!field.getType().equals(Integer.class)){
            H3cIotExceptionUtil.errorInAnnotationConfiguration(fieldName);
        }
        //验证canNull
        if (!verifyInteger.canNull()) {
            VerifyUtil.verifyObjectNull(fieldName, iValue, verifyInteger.message());
        }
        //验证max
        if (verifyInteger.max() != Integer.MAX_VALUE) {
            VerifyUtil.verifyMax(fieldName, iValue, verifyInteger.message(),
                    verifyInteger.min(), verifyInteger.max());
        }
        //验证min
        if (verifyInteger.min() != Integer.MIN_VALUE) {
            VerifyUtil.verifyMin(fieldName, iValue, verifyInteger.message(),
                    verifyInteger.min(), verifyInteger.max());
        }
    }


    private void verifyString(Field field,String fieldName, String sValue, VerifyString verifyString) {
        if (!field.getType().equals(String.class)){
            H3cIotExceptionUtil.errorInAnnotationConfiguration(fieldName);
        }
        //验证canEmpty
        if (!verifyString.canEmpty()) {
            VerifyUtil.verifyStringEmpty(fieldName, sValue, verifyString.message());
        }

        //验证maxLength
        if (verifyString.maxLength() > 0) {
            VerifyUtil.verifyStringEmpty(fieldName, sValue, verifyString.message());
            VerifyUtil.verifyMax(fieldName, sValue.length(), verifyString.message(),
                    verifyString.minLength(), verifyString.maxLength());
        }
        //验证minLength
        if (verifyString.minLength() > 0) {
            VerifyUtil.verifyStringEmpty(fieldName, sValue, verifyString.message());
            VerifyUtil.verifyMin(fieldName, sValue.length(), verifyString.message(),
                    verifyString.minLength(), verifyString.maxLength());
        }
        //验证matching
        if (!StringUtils.isEmpty(verifyString.matching().getReg())) {
            VerifyUtil.verifyMatching(fieldName,sValue,verifyString.message(),verifyString.matching().getReg(),
                    verifyString.matching().getMsg());
        }
    }




}
